/** This class was placed in this package because it can also be seen as a 'factory' for a
 * complete LightWeightScene object.
 * 
 */
package br.ufpe.cin.imlm2.jbeat.model.factory;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;

import br.ufpe.cin.imlm2.jbeat.model.LightWeightScene;

/**
 * This class is responsible for reading a class dump from a given input stream.
 * Usually the LightWeightScene is too complex to read for a standard thread
 * that's why a new thread with a higher maxStack value must be created.
 * Although the reading process is done in a different thread the readDump
 * method will block until the reading process is complete.
 * 
 * @author irineu
 */
public class DumpReader {

	private static final int DUMP_READER_THREAD_STACK_SIZE = 6291456;
	private final ObjectInputStream reader;
	private LightWeightScene scene;
	private Exception readException;

	public DumpReader( InputStream is ) throws IOException {
		if ( is == null )
			throw new IllegalArgumentException( "Input stream can't be null." );
		this.reader = new ObjectInputStream( is );
	}

	private class ReaderThread implements Runnable {

		@Override
		public void run() {
			try {
				DumpReader.this.scene = (LightWeightScene) DumpReader.this.reader.readObject();
			} catch ( IOException e ) {
				DumpReader.this.readException = e;
			} catch ( ClassNotFoundException e ) {
				DumpReader.this.readException = e;
			}
		}

	}

	public synchronized LightWeightScene readDump() throws DumpReadException {
		this.readException = null;
		// The LightWeightScene is a complex object so we need enough stack size
		// to read it.
		Thread t = new Thread( null, new ReaderThread(), "DumpReaderThread", DUMP_READER_THREAD_STACK_SIZE );
		try {
			t.start();
			t.join();
		} catch ( InterruptedException e ) {
			throw new DumpReadException( e );
		}
		if ( this.readException != null ) {
			throw new DumpReadException( this.readException );
		}
		return this.scene;
	}

}
